// File: jmcomic-core/src/main/java/dev/jukomu/common/base/registry/ComponentRegistry.java
package dev.jukomu.common.base.registry;

import dev.jukomu.common.util.Asserts;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 对应Python的ComponentRegistry，用于注册和管理组件（例如插件、客户端实现）。
 */
public class ComponentRegistry {

    // 使用ConcurrentHashMap来存储注册表，确保线程安全
    // 外层Map: interface -> (inner Map: key -> implementationClass)
    private static final Map<Class<?>, Map<String, Class<?>>> registry = new ConcurrentHashMap<>();

    /**
     * 注册组件。
     *
     * @param interfaceClass        组件的接口类或抽象类
     * @param keyFieldName          字段名，该字段的值将作为组件的唯一键（例如 "plugin_key", "client_key"）
     * @param implementationClasses 实现了该接口的组件实现类集合
     * @param requireKeyField       如果为true，则要求实现类必须包含keyFieldName字段，否则抛出AssertionError
     * @return 注册成功的组件Map (key -> implementationClass)
     * @throws AssertionError 如果requireKeyField为true但实现类缺少keyFieldName字段
     */
    public static Map<String, Class<?>> registerComponent(
            Class<?> interfaceClass,
            String keyFieldName,
            Collection<Class<?>> implementationClasses,
            boolean requireKeyField
    ) {
        registry.putIfAbsent(interfaceClass, new ConcurrentHashMap<>());
        Map<String, Class<?>> innerRegistry = registry.get(interfaceClass);

        for (Class<?> clazz : implementationClasses) {
            // 确保是接口的子类且不是接口本身
            if (interfaceClass.isAssignableFrom(clazz) && !clazz.equals(interfaceClass)) {
                try {
                    // 通过反射获取keyFieldName的值
                    java.lang.reflect.Field keyField = clazz.getField(keyFieldName);
                    String key = (String) keyField.get(null); // 获取静态字段的值

                    innerRegistry.put(key, clazz);
                } catch (NoSuchFieldException e) {
                    if (requireKeyField) {
                        Asserts.requireTrue(false,
                                "Register failed, " + clazz.getName() + " must have a public static final String \"" + keyFieldName + "\" field."
                        );
                    }
                } catch (IllegalAccessException e) {
                    Asserts.requireTrue(false,
                            "Register failed, cannot access " + keyFieldName + " field in " + clazz.getName() + ". It must be public static."
                    );
                } catch (ClassCastException e) {
                    Asserts.requireTrue(false,
                            "Register failed, " + keyFieldName + " field in " + clazz.getName() + " must be a String."
                    );
                }
            }
        }
        return innerRegistry;
    }

    /**
     * 获取指定接口的某个键对应的实现类。
     *
     * @param interfaceClass 组件的接口类
     * @param key            键
     * @param <T>            接口类型
     * @return 实现类
     * @throws AssertionError 如果接口未注册或键不存在
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<? extends T> getImplClass(Class<T> interfaceClass, String key) {
        Map<String, Class<?>> innerRegistry = registry.get(interfaceClass);
        Asserts.requireTrue(innerRegistry != null, "Interface " + interfaceClass.getName() + " not found in registry.");

        Class<?> clazz = innerRegistry.get(key);
        Asserts.requireTrue(clazz != null, "Key \"" + key + "\" not found in registry of " + interfaceClass.getName() + ".");

        return (Class<? extends T>) clazz;
    }

    /**
     * 获取指定接口的所有实现类Map。
     *
     * @param interfaceClass 组件的接口类
     * @return 所有实现类Map (key -> implementationClass)
     */
    public static Map<String, Class<?>> getAllImpl(Class<?> interfaceClass) {
        Map<String, Class<?>> innerRegistry = registry.get(interfaceClass);
        return innerRegistry != null ? Collections.unmodifiableMap(innerRegistry) : Collections.emptyMap();
    }

    // 私有构造函数，防止实例化
    private ComponentRegistry() {
    }
}